<?php declare(strict_types=1);

namespace App\Console\Commands;


use App\Api\Controllers\Merchant\OrderController;
use App\Models\Bi\BiOrder;
use App\Models\Order;
use App\Services\PrintSqlService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Tymon\JWTAuth\Facades\JWTAuth;

class MoveOrderToBiCommand extends Command
{


    protected $signature = 'move_order_to_bi {day?}';


    protected $description = 'move_order_to_bi';

    public function __construct()
    {
        parent::__construct();
    }

    public function getCreatedAtRange(string $string, int $value)
    {
        switch ($value) {
            case 0:
                $startDate = $string . " 00:00:00";
                $endDate = $string . " 08:59:59";
                break;
            case 1:
                $startDate = $string . " 09:00:00";
                $endDate = $string . " 11:59:59";
                break;
            case 2:
                $startDate = $string . " 12:00:00";
                $endDate = $string . " 14:59:59";
                break;
            case 3:
                $startDate = $string . " 15:00:00";
                $endDate = $string . " 17:59:59";
                break;
            case 4:
                $startDate = $string . " 18:00:00";
                $endDate = $string . " 20:59:59";
                break;
            case 5:
                $startDate = $string . " 21:00:00";
                $endDate = $string . " 23:59:59";
                break;
            default :
                throw new \Exception("Value范围错误");
        }
        return [$startDate, $endDate];
    }

    //同步订单状态
    public function handle()
    {
        //运行定时任务
        Log::channel("syncOrder")->info("move_order_to_bi" . date("Y-m-d H:i:s", time()));
        $yesterday = $this->argument('day');
        if (empty($yesterday)) {
            $yesterday = date("Y-m-d", strtotime("-1 day"));
        } else {
            $yesterday = date("Y-m-d", strtotime($yesterday . " 00:00:00"));
        }
        $tableName = "orders_" . date("Ym", strtotime($yesterday . " 00:00:00"));
        $shmId = shmop_open(1234, "c", 0644, 100);

        //任务拆分，写入对账数据库
        $numProcesses = 6;   //  每4个小时一个进程
        $processesPid = [];
        for ($i = 0; $i < $numProcesses; $i++) {
            $pid = pcntl_fork();
            if ($pid == -1) {
                dump('Could not fork');
                exit();
            } elseif ($pid) {
                // 父进程
                $processesPid[] = $pid;
                shmop_write($shmId, (string)$i, 0);
            } else {
                $value = (int)shmop_read($shmId, 0, 100);
                list($startDate, $endDate) = $this->getCreatedAtRange($yesterday, $value);
                //设置同的时间段
                dump($startDate . "----" . $endDate . "        进程编号:" . $value . "  进程ID:" . posix_getpid());
                // 这里可以编写子进程处理数据的逻辑
                $this->moveOrder($tableName, $startDate, $endDate);
                // 示例：简单打印数据
                exit(0); // 子进程执行完毕后退出
            }
        }
        //父进程等待所有子进程完成
        foreach ($processesPid as $process) {
            $status = 0;
            $childPid = pcntl_waitpid($process, $status);
            if ($childPid != -1) {
                $status = pcntl_wexitstatus($status);
//                $this->info('子进程结束: ' . $childPid);
            }
        }
        shmop_close($shmId);
        Log::channel("syncOrder")->error("move_order_to_bi" . date("Y-m-d H:i:s", time()));
    }

    protected function moveOrder(string $tableName, string $startDate, string $endDate)
    {

        PrintSqlService::listen();
        dump("moveOrder____" . $startDate . "----" . $endDate);
        //获取昨日的数据，写入对账数据库
        $orderYield = Order::query()->whereBetween("created_at", [$startDate, $endDate])->cursor();
        while ($orderYield->valid()) {
            $currentOrder = $orderYield->current();
            $this->writeOrder($currentOrder, $tableName);
            $orderYield->next();
        }
    }


    public function writeOrder(Order $order, string $tableName): void
    {
        $biOrder = BiOrder::query()->from($tableName)->where("out_trade_no", $order->out_trade_no)->first();
        if (!empty($biOrder)) {
            return;
        }
        $writeOrder = $order->toArray();
        unset($writeOrder["id"]);
        BiOrder::query()->from($tableName)->insert($writeOrder);
    }


}
